;; This file is part of scheme-GNUnet, a partial Scheme port of GNUnet.
;; Copyright (C) 2021 Maxime Devos <maximedevos@telenet.be>
;;
;; scheme-GNUnet is free software: you can redistribute it and/or modify it
;; under the terms of the GNU Affero General Public License as published
;; by the Free Software Foundation, either version 3 of the License,
;; or (at your option) any later version.
;;
;; scheme-GNUnet is distributed in the hope that it will be useful, but
;; WITHOUT ANY WARRANTY; without even the implied warranty of
;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
;; Affero General Public License for more details.
;;
;; You should have received a copy of the GNU Affero General Public License
;; along with this program.  If not, see <http://www.gnu.org/licenses/>.
;;
;; SPDX-License-Identifier: AGPL-3.0-or-later
(import (gnu gnunet util time)
	(srfi srfi-26)
	(srfi srfi-43))

(test-begin "time")

(test-equal "back-off factor correct"
  2
  (/ (standard-back-off (* 2 time-unit:second))
     (standard-back-off time-unit:second)))

(test-assert "not stuck at zero"
  (> (standard-back-off 0)))

(define %small-relative-times
  (list time-unit:millisecond time-unit:second
	time-unit:minute))

(define %very-small-relative-times
  (map (cut * <> time-unit:microsecond)
       '(0 1 2 3 4 #e1e1 #e1e2 #e1e3)))

(test-equal "minimum is 1 milliseconds"
  (map standard-back-off %very-small-relative-times)
  (map (const (standard-back-off time-unit:millisecond))
       %very-small-relative-times))

(test-equal "back-off is (at first) exponential (factor: 2)"
  (map (cut * 2 <>) %small-relative-times)
  (map standard-back-off %small-relative-times))

(test-assert "15 minutes is a fixed point"
  (standard-back-off (* 15 time-unit:minute)))

(define deltas '(1 2 3 #e1e1 #e1e3 #e1e4 #e1e5 #e1e9 #e1e20))
(test-equal "bounded to 15 minutes"
  (map (const (* 15 time-unit:minute)) deltas)
  (map (compose standard-back-off (cut + (* 15 time-unit:minute) <>))
       deltas))

(define %fractions>=1/2 '(1/2 3/4 5/8 9/16 17/32))
(test-equal "bounded to 15 minutes (slightly smaller start time)"
  (map (compose standard-back-off
		(cut * <> (* 15 time-unit:minute))) %fractions>=1/2)
  (map (const (* 15 time-unit:minute)) %fractions>=1/2))

(test-error "no inexact numbers"
  (standard-back-off 0.0))

(test-error "no integers rationals"
  (standard-back-off 0.0))

(test-error "no strictly negative numbers"
  (standard-back-off -1))

(test-end "time")
